<?php
///////////////////////////////////////////////////////////////////////////////////////////////////////
//  这个文件是 JCAT PHP框架的一部，该项目和此文件 均遵循 GNU 自由软件协议
// 
//  Copyleft 2008 JeCat.cn(http://team.JeCat.cn)
//
//
//  JCAT PHP框架 的正式全名是：Jellicle Cat PHP Framework。
//  “Jellicle Cat”出自 Andrew Lloyd Webber的音乐剧《猫》（《Prologue:Jellicle Songs for Jellicle Cats》）。
//  JCAT 是一个开源项目，它像音乐剧中的猫一样自由，你可以毫无顾忌地使用JCAT PHP框架。JCAT 由中国团队开发维护。
//  正在使用的这个版本是：0.5.0 / SVN信息: $Id: class.JCAT_UICtrlHtmlMenu.php 1680 2009-04-17 13:15:06Z alee $
//
//
//
//  相关的链接：
//    [主页] http://jcat.JeCat.cn
//    [下载(HTTP)] http://code.google.com/p/jcat-php/downloads/list
//    [下载(svn)] svn checkout http://jcat-php.googlecode.com/svn/branches/0.4.0/Framework/ JCAT0.4
//    [在线文档] http://jcat.JeCat.cn/document
//    [社区] http://jj.jecat.cn/forum-7-1.html
//  不很相关：
//    [MP3] http://www.google.com/search?q=jellicle+songs+for+jellicle+cats+Andrew+Lloyd+Webber
//    [VCD/DVD] http://www.google.com/search?q=CAT+Andrew+Lloyd+Webber+video
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
/*-- Project Introduce --*/


/**
 * What's this Class ?
 *
 * @author		alee
 * @access		public
 */
class JCAT_UICtrlHtmlMenu extends JCAT_UICtrlHtmlBase implements JCAT_IUICtrlHtmlMenu
{
	
	const HORIZONTAL = 1 ;
	
	const VERTICALITY = 2 ;
	
	const DEFAULT_THEME_NAME = __CLASS__ ;
	
	const CSSITEM_HORIZONTAL = 'Horizontal' ;
	const CSSITEM_ACTIVE = 'ActiveItem' ;
	const CSSITEM_UNACTIVE = 'UnactiveItem' ;
	const CSSITEM_LINK = 'ItemLink' ;
	const CSSITEM_MENUITEM = 'Item' ;
	
	/**	
	 *
	 * @access	public
	 * @return	void
	 */
	public function JCAT_UICtrlHtmlMenu( $sName, JCAT_CSSTheme $aCSSTheme=null, $sUIName='', JCAT_UIHtml $aUI=null )
	{
		$this->JCAT_UICtrlHtmlBase($sName,$sUIName,$aUI) ;
		$this->sMainUITemplate = dirname(__FILE__).'/../../Resource/template.JCAT_UICtrlHtmlMenu.html' ;

		// 主题
		if(!$aCSSTheme)
		{
			$aCSSTheme = self::DefineTheme($this->GetUI()) ;
		}
		$this->SetCSSTheme($aCSSTheme) ;
		
		// 设置菜单方向
		$this->SetDirection(self::VERTICALITY) ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @static
	 * @return	JCAT_CSSTheme
	 */
	static public function DefineTheme(JCAT_UIHtml $aUI)
	{
		$aTheme = new JCAT_CSSTheme('',self::DEFAULT_THEME_NAME) ;
		
		// file
		$aTheme->DefineFile(self::DEFAULT_THEME_NAME.'.css',$aUI) ;
		
		// items
		$aTheme->DefineItem(JCAT_CSSTheme::DEFAULT_ITEM) ;
		$aTheme->DefineItem(self::CSSITEM_HORIZONTAL) ;
		$aTheme->DefineItem(self::CSSITEM_ACTIVE) ;
		$aTheme->DefineItem(self::CSSITEM_UNACTIVE) ;
		$aTheme->DefineItem(self::CSSITEM_LINK) ;
		$aTheme->DefineItem(self::CSSITEM_MENUITEM) ;
		
		return $aTheme ;
	}

	/**
	 * 添加菜单项目
	 *
	 * @access	public
	 * @param	
	 * @return	void
	 */
	public function AddItem(JCAT_IUICtrlHtmlMenuItem $aMenuItem)
	{
		if( !in_array($aMenuItem,$this->arrMenuItems,true) )
		{
			$this->arrMenuItems[$aMenuItem->GetItemText()] = $aMenuItem ;
		}
		
		$aMenuItem->SetParentMenu($this) ;
	}

	/**
	 * Description
	 *
	 * @access	public
	 * @param	$sText
	 * @return	JCAT_IUICtrlHtmlMenuItem
	 */
	public function GetItem($sText,$bRecursion=false)
	{
		if(!$bRecursion)
		{
			return isset($this->arrMenuItems[$sText])? $this->arrMenuItems[$sText]: null ;
		}
		
		else 
		{
			$aIterator = $this->CreateItemIterator(true) ;
			for ( $aIterator->First(); !$aIterator->IsDone(); $aIterator->Next() )
			{
				$aItem = $aIterator->Current() ;
				if( $aItem->GetItemText()==$sText )
				{
					return $aItem ;
				}
			}
			
			return null ;
		}
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @return	void
	 */
	public function ClearItem()
	{
		$this->arrMenuItems = array() ;
	}

	/**
	 * 返回 Item 的数量
	 *
	 * @access	public
	 * @return	int
	 */
	public function GetItemCount()
	{
		return count($this->arrMenuItems) ;
	}

	/**
	 * 设置对象属性 self::$nDirection
	 *
	 * @access	public
	 * @param	$nDirection		int	菜单方向
	 * @return	void
	 */
	public function SetDirection($nDirection)
	{
		$this->nDirection = $nDirection ;
	}

	/**
	 * 取得对象属性 self::$nDirection
	 *
	 * @access	public
	 * @return	int
	 */
	public function GetDirection()
	{
		return $this->nDirection ;
	}
	
	
	/**
	 * Description
	 *
	 * @access	public
	 * @return	string
	 */
	public function GetClassNameStream()
	{
		$arrStyleItems = array(JCAT_CSSTheme::DEFAULT_ITEM) ;
		if( $this->GetDirection()==self::HORIZONTAL )
		{
			$arrStyleItems[] = self::CSSITEM_HORIZONTAL ;
		}
		
		$aTheme = $this->GetCSSTheme() ;
		$sClassForTheme = $aTheme->GetClassName($arrStyleItems) ;
		
		if(!$sClassForTheme)
		{
			$sClassForTheme.= ' ' ;
		}
		return $sClassForTheme.parent::GetClassNameStream() ;
	}
	

	
	/**
	 * 设置菜单的深度, start from 0
	 *
	 * @access	public
	 * @param	$nDepth
	 * @return	void
	 */
	public function SetDepth($nDepth)
	{
		$this->nDepth = $nDepth ;
	}
	
	/**
	 * 取得菜单的深度, start from 0
	 *
	 * @access	public
	 * @return	int
	 */
	public function GetDepth()
	{
		return $this->nDepth ;
	}

	/**
	 * Description
	 *
	 * @access	public
	 * @param	$sText
	 * @return	JCAT_IUICtrlHtmlMenuItem
	 */
	public function FindItemByText($sText,$bRecursion=false)
	{
		return $this->GetItem($sText,$bRecursion) ;
	}
	
	/**
	 * 返回是否缩进
	 *
	 * @access	public
	 * @return	bool
	 */
	public function IsLevelIndent()
	{
		return ($this->GetDirection()==self::VERTICALITY) ;
	}

	
	/**
	 * 返回缩进长度
	 *
	 * @access	public
	 * @return	string
	 */
	public function GetIndent()
	{
		return strval($this->GetDepth()*$this->nIndent) . 'px' ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @param	$nIndent			int
	 * @param	$bRecursion=true	bool
	 * @return	void
	 */
	public function SetIndent($nIndent,$bRecursion=true)
	{
		$this->nIndent = $nIndent ;
		
		if($bRecursion)
		{
			foreach( $this->arrMenuItems as $aMenuItem )
			{
				$aMenu = $aMenuItem->GetChildMenu() ;
				
				if($aMenu)
				{
					$aMenu->SetIndent($nIndent,$bRecursion) ;
				}
			}
		}
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @return	JCAT_IIterator
	 */
	public function CreateItemIterator($bRecursion=false)
	{
		$aIterator = new JCAT_ArrayIterator($this->arrMenuItems) ;
		if(!$bRecursion)
		{
			return $aIterator ;
		}
		
		else
		{
			$arrIterators = array($aIterator) ;
			
			for ( $aIterator->First(); !$aIterator->IsDone(); $aIterator->Next() )
			{
				$aItem = $aIterator->Current() ;
				$aChildMenu = $aItem->GetChildMenu() ;
				
				if($aChildMenu)
				{
					$arrIterators[] = $aChildMenu->CreateItemIterator(true) ;
				}
			}
			
			return new JCAT_MultiIterator($arrIterators) ;
		}
	}
	
	
	/**
	 * Description
	 *
	 * @access	public
	 * @param	$sXML					string
	 * @param	$bClearBefore=false		string
	 * @return	void
	 */
	public function BuildMenuFromXML($sXML,$bClearBefore=false,$sLanguageName=null)
	{
		if( !$aXMLDom=simplexml_load_string ($sXML) )
		{
			throw new JCAT_Exception(JCAT_Language::SentenceEx(
				'传入的 XML数据存在结构错误', 'JCAT', null
			)) ;
		}
		
		if($bClearBefore)
		{
			$this->ClearItem() ;
		}
		
		// $aXMLDom
		$this->LoadMenuItemsFromXML($aXMLDom,$sLanguageName) ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @param	$Parameter
	 * @return	void
	 */
	public function LoadMenuItemsFromXML(SimpleXMLElement $aXML,$sLanguageName=null)
	{
		foreach ($aXML->xpath('MenuItem') as $aMenuItemDom)
		{
			if( !isset($aMenuItemDom['text']) or !isset($aMenuItemDom['package']) )
			{
				throw new JCAT_Exception(JCAT_Language::SentenceEx(
					'MenuItem 缺少必要得属性:text 或 package (%s)'
					, 'JCAT', null, $aMenuItemDom->asXML()
				)) ;
			}
			
			$sOnClick = isset($aMenuItemDom['onclick'])? $aMenuItemDom['onclick']: null ;
			$sLink = isset($aMenuItemDom['link'])? $aMenuItemDom['link']: null ;
			$sText = JCAT_Language::Sentence(strval($aMenuItemDom['text']),strval($aMenuItemDom['package']),$sLanguageName) ;
			$sTarget = isset($aMenuItemDom['target'])? $aMenuItemDom['target']: null ;
			if(isset($aMenuItemDom['active']))
			{
				$bActive = !in_array(strtolower($aMenuItemDom['active']),array('false','0','off','no')) ;
			}
			
			else 
			{
				$bActive = false ;
			}
			
			$aItem = $this->FindItemByText($sText) ;
			if(!$aItem)
			{
				$aItem = new JCAT_UICtrlHtmlMenuItem($this,$sText,$sLink,$bActive,$this->GetUI()) ;
				$this->AddItem($aItem) ;
			}
			
			else 
			{
				if($sLink!==null)
				{
					$aItem->SetLink($sLink) ;
				}
				$aItem->SetActive($bActive) ;
			}

			if($sOnClick!==null)
			{
				$aItem->SetOnClick($sOnClick) ;
			}
			
			$aItem->SetTarget($sTarget) ;

			// 递归下级菜单
			if( $aMenuItemDom->xpath('MenuItem') )
			{
				$aChildMenu = $aItem->GetChildMenu() ;
				if(!$aChildMenu)
				{
					$aChildMenu = new self(
						$this->GetName().":{$sText}"
						, $this->GetCSSTheme()
						, '', $this->GetUI()
					) ;
					
					$aItem->SetChildMenu($aChildMenu) ;
				}
				
				$aChildMenu->LoadMenuItemsFromXML($aMenuItemDom,$sLanguageName) ;
			}
		}
	}
	
	/**
	 * 参数 $arrSort 是一个多维数组，表示菜单的顺序
	 * $arrSort 的结构为： 
	 * array(
	 * 	'Item Text' => null ,
	 * 	'Item Text' => array(
	 * 		'Child Item Text' => null
	 * 	) 
	 * )
	 * 
	 *
	 * @access	public
	 * @param	$arrSort
	 * @return	void
	 */
	public function SortMenuItems(array $arrSort)
	{
		$arrOldItems = $this->arrMenuItems ;
		$arrNewItems = array() ;
		
		foreach ($arrSort as $sMenuText=>$arrChildMenu)
		{
			if( isset($arrOldItems[$sMenuText]) )
			{
				$arrNewItems[$sMenuText] = $arrOldItems[$sMenuText] ;
				unset($arrOldItems[$sMenuText]) ;
				
				// 递归下级
				$aChildMenu = $arrNewItems[$sMenuText]->GetChildMenu() ;
				if( $aChildMenu and is_array($arrChildMenu) )
				{
					$aChildMenu->SortMenuItems($arrChildMenu) ;
				}
			}
		}
		
		$this->arrMenuItems = $arrNewItems + $arrOldItems ;
	}
	
	/**
	 * SortMenuItems() 的逆向操作
	 *
	 * @access	public
	 * @return	array
	 */
	public function GetMenuOrder()
	{
		$arrOrder = array() ;
		
		foreach($this->arrMenuItems as $sMenuText=>$aMenuItem)
		{
			$aChildMenu = $aMenuItem->GetChildMenu() ;
			$arrOrder[$sMenuText] = $aChildMenu? $aChildMenu->GetMenuOrder(): null ;
		}
		
		return $arrOrder ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @param	$arrPath		array
	 * @return	void
	 */
	public function GetChildMenu($arrPath)
	{
		$sText = array_shift($arrPath) ;
		$aMenuItem = $this->FindItemByText($sText) ;
		if(!$aMenuItem)
		{
			return ;
		}
		$aChildMenu = $aMenuItem->GetChildMenu() ;
		
		if(!$aChildMenu)
		{
			return null ;
		}
		
		else if( empty($arrPath) )
		{
			return $aChildMenu ;
		}
		
		else
		{
			return $aChildMenu->GetChildMenu($arrPath) ;
		}
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @param	$arrPath		array
	 * @param	$bActive=true	bool
	 * @return	void
	 */
	public function SetActiveByPath($arrPath,$bActive=true)
	{
		$sText = array_shift($arrPath) ;
		$aMenuItem = $this->FindItemByText($sText) ;
		if(!$aMenuItem)
		{
			return ;
		}
		
		$aMenuItem->SetActive($bActive);
		
		$aChildMenu = $aMenuItem->GetChildMenu() ;
		if( $aChildMenu and !empty($arrPath))
		{
			$aChildMenu->SetActiveByPath($arrPath,$bActive) ;
		}
	}

	/**
	 * Description
	 *
	 * @access	public
	 * @param 	$aMenuItem	JCAT_IUICtrlHtmlMenuItem
	 * @static
	 * @return	array
	 */
	static public function TracePath(JCAT_IUICtrlHtmlMenuItem $aMenuItem,$bReturnName=true)
	{
		$aActiveItem = $aMenuItem ;
		$arrPath = array() ;
		
		while($aActiveItem)
		{
			$arrPath[] = $bReturnName? $aActiveItem->GetItemText(): $aActiveItem ;
			
			$aParentMenu = $aActiveItem->GetParentMenu() ;
			$aActiveItem = $aParentMenu->GetParentItem() ;
		}
		
		return array_reverse($arrPath) ;
	}
	
	/**
	 * 设置对象属性 self::$aParentItem
	 *
	 * @access	public
	 * @param	$aParentItem		JCAT_IUICtrlHtmlMenuItem	PropertyDescription
	 * @return	void
	 */
	public function SetParentItem(JCAT_IUICtrlHtmlMenuItem $aParentItem)
	{
		$this->aParentItem = $aParentItem ;
	}
	
	/**
	 * 取得对象属性 self::$aParentItem
	 *
	 * @access	public
	 * @return	JCAT_IUICtrlHtmlMenuItem
	 */
	public function GetParentItem()
	{
		return $this->aParentItem ;
	}
	
	// 属性 ///////////////////////////////////
	
	/**
	 * 菜单项目
	 * 
	 * @access	private
	 * @var		array
	 */
	private $arrMenuItems = array() ;
	
	
	/**
	 * 对象属性 菜单方向
	 * 
	 * @access	private
	 * @var		int
	 */
	private $nDirection ;
	
	/**
	 * Description
	 * 
	 * @access	private
	 * @var		int
	 */
	private $nDepth = 0 ;
	
	/**
	 * Description
	 * 
	 * @access	private
	 * @var		int
	 */
	private $nIndent = 20 ;
	
	
	/**
	 * 对象属性 PropertyDescription
	 * 
	 * @access	private
	 * @var		JCAT_IUICtrlHtmlMenuItem
	 */
	private $aParentItem ;
	
}

?>